#include "moveStates.h"
#include "moveStateMachine.h"

#include "../clientSidePlayer.h"
#include "../../client/clientSideClient.h"
#include "../../shape/ogreShape.h"

#include "../../tdreamsock/dreamSock.h"



Normal_Move* Normal_Move::Instance()
{
  static Normal_Move instance;
  return &instance;
}
void Normal_Move::enter(ClientSidePlayer* player)
{
	LogString("STATE: Normal_Move");
}
void Normal_Move::execute(ClientSidePlayer* player)
{
	float deltaX = player->mClient->mServerFrame.mOrigin.x - player->mShape->getSceneNode()->getPosition().x;
    float deltaZ = player->mClient->mServerFrame.mOrigin.z - player->mShape->getSceneNode()->getPosition().z;

	float dist = sqrt(pow(deltaX, 2) + pow(deltaZ, 2));

	  if(dist > 8.0)
	   {
          player->mClient->mCommand.mCatchup = true;
		  
	   }

	   if(dist < 2.0)
          player->mClient->mCommand.mCatchup = false;



	   if(player->mClient->mServerFrame.mVelocity.x == 0.0 && player->mClient->mServerFrame.mVelocity.z == 0.0)
	   {
		   player->mClient->mCommand.mStop = true;
	   }
	   else
	   {
          player->mClient->mCommand.mStop = false;
	   }

	   if(player->mClient->mCommand.mCatchup == true && player->mClient->mCommand.mStop == false)
	   {

		   //send to catchup state...
		   player->moveStateMachine->changeState(Catchup_Move::Instance());

	   }
	   else
	   {
          Ogre::Vector3 serverDest  = Ogre::Vector3::ZERO;
		  Ogre::Vector3 myDest      = Ogre::Vector3::ZERO;

	      serverDest.x = player->mClient->mServerFrame.mVelocity.x;
		  serverDest.z = player->mClient->mServerFrame.mVelocity.z;
		  serverDest.normalise();
          serverDest = serverDest * 0.2;

		  player->mClient->mCommand.mVelocity.x = serverDest.x;
	      player->mClient->mCommand.mVelocity.z = serverDest.z;
	   }
}
void Normal_Move::exit(ClientSidePlayer* player)
{
}

Catchup_Move* Catchup_Move::Instance()
{
  static Catchup_Move instance;
  return &instance;
}
void Catchup_Move::enter(ClientSidePlayer* player)
{
	LogString("STATE: Catchup_Move");
}
void Catchup_Move::execute(ClientSidePlayer* player)
{

	if(player->mClient->mCommand.mCatchup == true && player->mClient->mCommand.mStop == false)
	{
		//these 3 lines are dup code from normal state need to ....condense..
		float deltaX = player->mClient->mServerFrame.mOrigin.x - player->mShape->getSceneNode()->getPosition().x;
		float deltaZ = player->mClient->mServerFrame.mOrigin.z - player->mShape->getSceneNode()->getPosition().z;

		float dist = sqrt(pow(deltaX, 2) + pow(deltaZ, 2));

		Ogre::Vector3 serverDest  = Ogre::Vector3::ZERO;
		Ogre::Vector3 myDest      = Ogre::Vector3::ZERO;

		serverDest.x = player->mClient->mServerFrame.mVelocity.x;
		serverDest.z = player->mClient->mServerFrame.mVelocity.z;
		serverDest.normalise();

		float multiplier = dist * 10.0;
		serverDest = serverDest * multiplier;
		serverDest.x = player->mClient->mServerFrame.mOrigin.x + serverDest.x;
		serverDest.z = player->mClient->mServerFrame.mOrigin.z + serverDest.z;

		myDest.x = serverDest.x - player->mShape->getSceneNode()->getPosition().x;
		myDest.z = serverDest.z - player->mShape->getSceneNode()->getPosition().z;


		float predictDist = pow(myDest.x, 2) + pow(myDest.z, 2);
		predictDist = sqrt(predictDist);
	
		myDest.normalise();

		float vel = sqrt(pow(player->mClient->mServerFrame.mVelocity.x, 2) + pow(player->mClient->mServerFrame.mVelocity.z, 2))/player->mClient->mCommand.mMilliseconds;
		//float time = dist * 10.0/vel;
		float time = dist * 10.0/0.2;

		myDest = myDest * predictDist/time;

		player->mClient->mCommand.mVelocity.x = myDest.x;
		player->mClient->mCommand.mVelocity.z = myDest.z;

	}
	else
	{
		//send back to normal state...
		player->moveStateMachine->changeState(Normal_Move::Instance());
	}
}
void Catchup_Move::exit(ClientSidePlayer* player)
{
}


Stop_Move* Stop_Move::Instance()
{
  static Stop_Move instance;
  return &instance;
}
void Stop_Move::enter(ClientSidePlayer* player)
{
	LogString("STATE: Stop_Move");
}
void Stop_Move::execute(ClientSidePlayer* player)
{
}
void Stop_Move::exit(ClientSidePlayer* player)
{
}